package com.netty.handler;

import com.netty.pojo.RpcResponse;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import com.netty.pojo.RpcRequest;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;

import java.lang.reflect.Method;

/**
 * @author : zhengyao3@郑瑶
 * @date : 2020/7/3 12:07
 * @Description: 服务Handler类，找到Server的本地处理类并进行处理
 */
@Service
@Qualifier("serverHandler")
@ChannelHandler.Sharable
public class ServerHandler extends ChannelInboundHandlerAdapter implements ApplicationContextAware {

    private ApplicationContext applicationContext;
    
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("进入serverHandler");
        if (msg instanceof RpcRequest) {
            RpcRequest rpcRequest = (RpcRequest) msg;
            //获取请求ID
            String requestId = rpcRequest.getRequestId();
            System.out.println("requestId = "+requestId);
            String className = rpcRequest.getClassName();
            Class clazz = Class.forName(className);
            //获取对应的实现类
            Object bean = applicationContext.getBean(clazz);
            String methodName = rpcRequest.getMethodName();
            //根据方法名和参数找到匹配的方法
            Method method = bean.getClass()
                    .getDeclaredMethod(methodName,rpcRequest.getParameterTypes());
            //反射调用方法
            Object result = method.invoke(bean, rpcRequest.getParameters());
            //封装返回值
            RpcResponse rpcResponse = new RpcResponse();
            rpcResponse.setObject(result);
            rpcResponse.setRequestId(requestId);
            ctx.writeAndFlush(rpcResponse);
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
